package me.chyxion.dao.mybatis.pagination;

import java.io.Serializable;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import me.chyxion.spring.ext.utils.ResponseTool;

/**
 * @version 0.0.2
 * @since 0.0.1
 * @author Shaun Chyxion <br />
 * chyxion@163.com <br />
 * Jul 4, 2014 9:01:03 PM
 */
public class PageParam<T> implements Serializable {
	private static final long serialVersionUID = 1L;
	
	private int start = 0;
	private int limit = 16;
	private List<Sort> sorts;
	private int total;
	private List<T> data;
	private boolean intercept;
	private boolean autoCount = true;

	/**
	 * @param start
	 * @param limit
	 * @param sorts
	 */
	public PageParam(int start, int limit, List<Sort> sorts) {
		this.start = start;
		this.limit = limit;
		this.sorts = sorts;
	}

	/**
	 * @param start
	 * @param limit
	 */
	public PageParam(int start, int limit) {
		this(start, limit, new LinkedList<Sort>());
	}

	/**
	 * @return the sort
	 */
	public List<Sort> getSorts() {
		return sorts;
	}
	/**
	 * @param sort the sort to set
	 */
	public void setSorts(List<Sort> sorts) {
		this.sorts = sorts;
	}

	public PageParam<T> addSort(String column, String direction) {
		if (StringUtils.isNotBlank(column) && 
				Pattern.matches("^\\w+$", column)) {
			Sort s = new Sort();
			s.column = column;
			s.direction = direction;
			sorts.add(s);
		}
		return this;
	}

	public PageParam<T> addSort(String column) {
		return this.addSort(column, null);
	}

	/**
	 * @return the start
	 */
	public int getStart() {
		return start;
	}
	/**
	 * @param start the start to set
	 */
	public void setStart(int start) {
		this.start = start;
	}
	/**
	 * @return the limit
	 */
	public int getLimit() {
		return limit;
	}
	/**
	 * @param limit the limit to set
	 */
	public void setLimit(int limit) {
		this.limit = limit;
	}

	public static class Sort {
		private String column;
		private String direction;

		/**
		 * @return the column
		 */
		public String getColumn() {
			return column;
		}

		/**
		 * @return the direction
		 */
		public String getDirection() {
			return StringUtils.isBlank(direction) || 
					ArrayUtils.contains(new String[] {
						"asc", "true", "1", "y", "yes" }, 
						direction.trim().toLowerCase()) ? 
    			"asc" : "desc";
		}
	}

	/**
	 * @return the autoCount
	 */
	public boolean isAutoCount() {
		return autoCount;
	}
	/**
	 * @param autoCount the autoCount to set
	 */
	public void setAutoCount(boolean autoCount) {
		this.autoCount = autoCount;
	}

	/**
	 * @return the total
	 */
	public int getTotal() {
		return total;
	}

	/**
	 * @param total the total to set
	 */
	public void setTotal(int total) {
		this.total = total;
	}

	/**
	 * @return the intercept
	 */
	boolean intercept() {
		return intercept;
	}

	/**
	 * @param intercept the intercept to set
	 */
	void setIntercept(boolean intercept) {
		this.intercept = intercept;
	}

	/**
	 * @return the data
	 */
	public List<T> getData() {
		return data;
	}

	/**
	 * @param data the data to set
	 */
	public List<T> setData(List<T> data) {
		return this.data = data;
	}

	public Map<String, Object> toMap() {
		Map<String, Object> mapData = new HashMap<String, Object>();
		mapData.put("total", total);
		mapData.put("data", data);
    	mapData.put("success", true);
		// keep raw data
		mapData.put(ResponseTool.MARK_RAW, true);
		return mapData;
	}
}
